package it.cinema.layar.biz;

import it.cinema.layar.CinemaServlet;
import it.cinema.layar.Response;
import it.cinema.layar.data.ActionData;
import it.cinema.layar.data.Hotspot;
import it.cinema.layar.data.HotspotData;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import javax.annotation.Resource;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

public class RequestBiz {
	private static final Logger log = Logger.getLogger(RequestBiz.class
			.getName());

	private DataSource ds;
	private static final float kmDeg = 111.22625f;
	private static String layerName = "filmslocator";

	public RequestBiz() {
		try {
			Context ctx = new InitialContext();
			ds = (DataSource) ctx.lookup("java:comp/env/jdbc/dbcinema");
		} catch (NamingException e) {
			e.printStackTrace();
		}
	}

	public Response handleRequest(float currLat, float currLon, int radius,
			int alt) {
		Response response = new Response();

		// Get all the active hotspots within the specified radius
		List<HotspotData> hotspots = getAll(currLat, currLon, radius);

		if (hotspots.size() > 0) {
			response.setHotspots(createAllHotspots(hotspots, currLat, currLon));
			response.setErrorCode(0);
			response.setErrorString("ok");
			response.setLayer(layerName);
			response.setRefreshDistance(10); // 10 meters
			response.setRefreshInterval(180); // 180 seconds
		} else {
			response.setErrorCode(20);
			response.setErrorString("No POI found. Please adjust the range.");
			response.setLayer(layerName);
			response.setRefreshDistance(10); // 10 meters
			response.setRefreshInterval(180); // 180 seconds
		}

		return response;
	}

	public List<HotspotData> getAll(float currLat, float currLon, int radius) {

		float delta[] = calculateDelta(radius / 1000, currLat);
		float latmin = currLat - delta[0];
		float latmax = currLat + delta[0];
		float lonmin = currLon - delta[1];
		float lonmax = currLon + delta[1];
		List<HotspotData> hotspots = new ArrayList<HotspotData>();
		List<ActionData> ads = null;

		ResultSet resultSet = null;
		Connection connection = null;
		Statement statement = null;
		HotspotData hsd = null;
		ActionData ad = null;

		try {
			// Get Connection and Statement
			connection = ds.getConnection();
			statement = connection.createStatement();

			// da modificare per recuperare solo i cinema che proiettono i film
			// ritornati
			// dalla ricerca semantica

			String query = "select distinct f.idfilm, c.idcinema, c.nome, c.lat, c.lon, c.indirizzo, c.citta, c.telefono, c.sito, c.zona"
					+ " from film f, cinema c, sala s, sala_proietta_film spf where c.idcinema = s.cinema_idcinema and s.idsala = spf.sala_idsala"
					+ " and c.idcinema = spf.sala_cinema_idcinema and spf.film_idfilm = f.idfilm order by c.idcinema";

			resultSet = statement.executeQuery(query);

			float lat = 0;
			float lon = 0;
			String idcinema = "";
			while (resultSet.next()) {
				lat = resultSet.getFloat("lat");
				lon = resultSet.getFloat("lon");
				if (lat >= latmin & lat <= latmax & lon >= lonmin & lon <= lonmax) {

					hsd = new HotspotData();
					idcinema = resultSet.getString("idcinema");
					hsd.setId(idcinema);
					hsd.setLat(resultSet.getFloat("lat"));
					hsd.setLon(resultSet.getFloat("lon"));
					hsd.setTitle(resultSet.getString("nome"));
					hsd.setLine4(resultSet.getString("citta"));
					hsd.setLine3(resultSet.getString("indirizzo"));
					hsd.setLine2(resultSet.getString("zona"));
					hsd.setImageURL("http://nomami.dlinkddns.com/CinemaLayarServices/content/cinema.jpg");

					ads = new ArrayList<ActionData>();

					StringBuffer films = new StringBuffer();
					films.append(resultSet.getString("idfilm"));
					while (resultSet.next()) {
						if (idcinema.equals(resultSet.getString("idcinema"))) {
							films.append("," + resultSet.getString("idfilm"));
						} else {
							resultSet.previous();
							break;
						}
					}
					if (resultSet.isAfterLast())
						resultSet.last();

					ad = new ActionData();
					ad.setLabel("Films Shown");
					ad.setUri("http://nomami.dlinkddns.com/CinemaLayarMobile?cinema="+idcinema+"&films="+films);
					ad.setContentType("text/html");
					ad.setActivityType(1);
					ads.add(ad);
					ad = new ActionData();
					ad.setLabel("Cinema Web Site");
					ad.setUri(resultSet.getString("sito"));
					ad.setContentType("text/html");
					ad.setActivityType(1);
					ads.add(ad);
					ad = new ActionData();
					ad.setLabel("Call Cinema");
					ad.setUri("tel:" + resultSet.getString("telefono"));
					ad.setContentType("application/vnd.layar.internal");
					ad.setActivityType(2);
					ads.add(ad);
					ad = new ActionData();
					ad.setLabel("Trailer");
					ad.setUri("http://www.mymovies.it/filmclub/2004/06/506/trailer.flv");
					ad.setContentType("video/flv");
					ad.setActivityType(3);
					ads.add(ad);
					hsd.setActions(ads);
					hotspots.add(hsd);
				}
			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if (null != resultSet)
					resultSet.close();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			try {
				if (null != statement)
					statement.close();
			} catch (SQLException e2) {
				e2.printStackTrace();
			}
			try {
				if (null != connection)
					connection.close();
			} catch (SQLException e3) {
				e3.printStackTrace();
			}
		}

		return hotspots;
	}

	private float[] calculateDelta(int radius, float lat) {
		float[] delta = new float[2];
		delta[0] = radius / kmDeg; // delta Lat
		delta[1] = radius / (float) (kmDeg * Math.cos(Math.toRadians(lat))); // delta
																				// Lon
		return delta;
	}

	public List<Hotspot> createAllHotspots(List<HotspotData> hotspots,
			float currLat, float currLon) {
		List<Hotspot> results = new ArrayList<Hotspot>();
		for (HotspotData hsd : hotspots) {
			results.add(hsd.createHotSpot(currLat, currLon));
		}
		return results;
	}
}
